home *** CD-ROM | disk | FTP | other *** search
- Path: uunet!wyse!mikew
- From: mikew@wyse.wyse.com (Mike Wexler)
- Newsgroups: comp.sources.x
- Subject: v00i009: Ardent Window Manager, Part09/13
- Message-ID: <1633@wyse.wyse.com>
- Date: 10 Aug 88 21:59:14 GMT
- Sender: news@wyse.wyse.com
- Lines: 1798
- Approved: mikew@wyse.com
-
- Submitted-by: unido!pcsbsd!jkh (Jordan Hubbard)
- Posting-number: Volume 0, Issue 9
- Archive-name: awm/part09
-
- [NOTE: Jordan Hubbard has moved. The first postings listed his
- address as jkh@ardent. His current address is unido!pcsbst!jkh]
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 9 (of 13)."
- # Contents: awm/GetButton.c awm/menus/track_menu.c
- # Wrapped by mikew@wyse on Mon Aug 8 12:01:47 1988
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f awm/GetButton.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"awm/GetButton.c\"
- else
- echo shar: Extracting \"awm/GetButton.c\" \(21347 characters\)
- sed "s/^X//" >awm/GetButton.c <<'END_OF_awm/GetButton.c'
- X#ident "%W% %G%"
- X
- X
- X
- X#ifndef lint
- Xstatic char *rcsid_GetButton_c = "$Header: GetButton.c,v 1.4 88/07/23 18:20:45 jkh Exp $";
- X#endif lint
- X
- X#include "X11/copyright.h"
- X/*
- X *
- X * Copyright 1987, 1988 by Ardent Computer Corporation, Sunnyvale, Ca.
- X *
- X * Copyright 1987 by Jordan Hubbard.
- X *
- X *
- X * All Rights Reserved
- X *
- X * Permission to use, copy, modify, and distribute this software and its
- X * documentation for any purpose and without fee is hereby granted,
- X * provided that the above copyright notice appear in all copies and that
- X * both that copyright notice and this permission notice appear in
- X * supporting documentation, and that the name of Ardent Computer
- X * Corporation or Jordan Hubbard not be used in advertising or publicity
- X * pertaining to distribution of the software without specific, written
- X * prior permission.
- X *
- X */
- X
- X/*
- X * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
- X *
- X * All Rights Reserved
- X *
- X * Permission to use, copy, modify, and distribute this software and its
- X * documentation for any purpose and without fee is hereby granted,
- X * provided that the above copyright notice appear in all copies and that
- X * both that copyright notice and this permission notice appear in
- X * supporting documentation, and that the name of Digital Equipment
- X * Corporation not be used in advertising or publicity pertaining to
- X * distribution of the software without specific, written prior permission.
- X *
- X *
- X * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
- X * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
- X * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
- X * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
- X * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
- X * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- X * SOFTWARE.
- X */
- X
- X
- X
- X/*
- X * MODIFICATION HISTORY
- X *
- X * 000 -- M. Gancarz, DEC Ultrix Engineering Group
- X * 001 -- L. Guarino Reid, DEC Ultrix Engineering Group, Western Software Lab
- X * February 16, 1987
- X * Add EnterWindow, LeaveWindow, and MouseMotion as recognized
- X * awm buttons for awm menus. Add bug fixes to prevent mem faults
- X * if icon_str is NULL.
- X * 002 -- L. Guarino Reid, DEC Ultrix Engineering Group
- X * April 16, 1987
- X * Convert to X11
- X * 003 -- J. Hubbard, U.C. Berkeley. Title/gadget box event handling.
- X * December 3, 1987.
- X * 004 -- J.Hubbard, Ardent Computer. More conformance with ICCCM. Merge of
- X * changes from R2 uwm.
- X */
- X
- X#ifndef lint
- Xstatic char *sccsid = "@(#)GetButton.c 3.8 1/24/86";
- X#endif
- X/*
- X * GetButton - This subroutine is used by the Ardent Window Manager (awm)
- X * to acquire button events. It waits for a button event to occur
- X * and handles all event traffic in the interim.
- X *
- X * File: GetButton.c
- X */
- X
- X#include "awm.h"
- X#include "X11/Xutil.h"
- X
- Xextern XContext AwmContext;
- Xextern Window FocusWindow;
- X
- X#define ICONSTR (icon_str ? icon_str : "")
- X/* Amount of padding between text in a title bar and the edge of the bar */
- X#define PAD 1
- X
- Xstatic Icon_modified = FALSE;
- X
- XBoolean GetButton(b_ev)
- XXEvent *b_ev; /* Button event packet. */
- X{
- X#define STRLEN 50
- X XKeyPressedEvent *kp_event; /* Key pressed event. */
- X char *icon_str; /* Icon's name string. */
- X register int icon_str_len; /* Icon name string lenght. */
- X register int key_char; /* Key press character code. */
- X register int icon_x; /* Icon window X coordinate. */
- X register int icon_y; /* Icon window Y coordinate. */
- X register int icon_w; /* Icon window width. */
- X register int icon_h; /* Icon window height. */
- X int status; /* Routine call return status. */
- X Window icon; /* Icon window. */
- X Window appl; /* Application window. */
- X XWindowAttributes win_info; /* Icon window info structure. */
- X char kbd_str[STRLEN]; /* Keyboard string. */
- X int nbytes; /* Keyboard string length. */
- X int i; /* Iteration counter. */
- X Window win; /* scratch */
- X AwmInfoPtr awi;
- X
- X Entry("GetButton")
- X
- X /*
- X * Get next event from input queue and store it in the event packet
- X * passed to GetButton.
- X */
- X
- X XNextEvent(dpy, b_ev);
- X /* print_event_info("mainloop", b_ev); /* debugging for event handling */
- X
- X /*
- X * The event occured on the root window, check for substructure
- X * changes. Otherwise, it must be a mouse button event.
- X */
- X
- X if (b_ev->xany.window == RootWindow(dpy, scr)) {
- X switch (b_ev->xany.type) {
- X case CreateNotify:
- X case UnmapNotify:
- X case ReparentNotify:
- X case ConfigureNotify:
- X case GravityNotify:
- X case MapNotify:
- X case CirculateNotify:
- X Leave(FALSE)
- X
- X case MappingNotify:
- X XRefreshKeyboardMapping(b_ev);
- X Leave(FALSE)
- X
- X case MapRequest:
- X CheckMap(b_ev->xmap.window);
- X Leave(FALSE)
- X
- X case ConfigureRequest:
- X Configure((XConfigureEvent *)b_ev);
- X Leave(FALSE)
- X
- X case CirculateRequest:
- X Circulate((XCirculateEvent *)b_ev);
- X Leave(FALSE)
- X
- X case DestroyNotify:
- X RemoveIcon(b_ev->xdestroywindow.window);
- X Leave(FALSE)
- X
- X case FocusIn:
- X if (b_ev->xfocus.detail == NotifyPointerRoot) {
- X if (FocusSetByUser) {
- X XSetInputFocus(dpy, PointerRoot, None,
- X CurrentTime);
- X FocusSetByUser = FALSE;
- X FocusWindow = RootWindow(dpy, scr);
- X }
- X }
- X Leave(FALSE)
- X
- X case FocusOut:
- X if (b_ev->xfocus.detail == NotifyPointerRoot) {
- X if (FocusSetByUser == FALSE && !FocusSetByWM) {
- X XSetInputFocus(dpy, PointerRoot, None,
- X CurrentTime);
- X FocusWindow = RootWindow(dpy, scr);
- X }
- X }
- X Leave(FALSE)
- X
- X case ButtonPress:
- X case ButtonRelease:
- X Leave(TRUE)
- X
- X default:
- X Leave(FALSE)
- X }
- X }
- X
- X /*
- X * If the event type is EnterWindow, LeaveWindow, or MouseMoved,
- X * we are processing a menu.
- X * If the event type is ButtonPress or ButtonRelease,
- X * we have a button event.
- X * If it's an expose, then we may have exposed a title bar.
- X * If it's a Notify, we've probably frobbed a titled window.
- X */
- X
- X switch (b_ev->type) {
- X XEvent e_fake;
- X
- X case MotionNotify:
- X case ButtonPress:
- X case ButtonRelease:
- X Leave(TRUE)
- X break;
- X
- X case FocusIn:
- X if (!FocusSetByWM) {
- X e_fake.xcrossing.type = FocusIn;
- X e_fake.xcrossing.focus = TRUE;
- X e_fake.xcrossing.window = b_ev->xcrossing.window;
- X HandleFocusIn(&e_fake);
- X }
- X Leave(FALSE)
- X break;
- X
- X case FocusOut:
- X if (!FocusSetByWM) {
- X e_fake.xcrossing.type = FocusOut;
- X e_fake.xcrossing.focus = TRUE;
- X e_fake.xcrossing.window = b_ev->xcrossing.window;
- X HandleFocusOut(&e_fake);
- X }
- X Leave(FALSE)
- X break;
- X
- X case EnterNotify:
- X HandleFocusIn(b_ev);
- X Leave(FALSE)
- X
- X case LeaveNotify:
- X HandleFocusOut(b_ev);
- X Leave(FALSE)
- X
- X case ConfigureRequest:
- X Configure((XConfigureEvent *)b_ev);
- X Leave(FALSE)
- X
- X case MapRequest:
- X CheckMap(b_ev->xmap.window);
- X Leave(FALSE);
- X
- X case MapNotify:
- X win = b_ev->xmap.window;
- X if (!(awi = GetAwmInfo(win)))
- X Leave(FALSE)
- X if (IsIcon(win, FALSE))
- X Leave(FALSE)
- X XMapWindow(dpy, awi->frame);
- X XMapWindow(dpy, awi->client);
- X Leave(FALSE)
- X break;
- X
- X case UnmapNotify:
- X win = b_ev->xunmap.window;
- X if (!(awi = GetAwmInfo(win)))
- X Leave(FALSE)
- X
- X if (IsIcon(win, FALSE))
- X Leave(FALSE)
- X XUnmapWindow(dpy, awi->frame);
- X Leave(FALSE)
- X break;
- X
- X case DestroyNotify:
- X win = b_ev->xdestroywindow.window;
- X if (!(awi = GetAwmInfo(win)))
- X Leave(FALSE)
- X if (win != awi->title) {
- X /* remove any icon associated with this window */
- X RemoveIcon(win);
- X /* remove the frame/titlebar (if present) */
- X NoDecorate(win, TRUE);
- X /* punt the rest of the per-window info */
- X XDeleteContext(dpy, awi->client, AwmContext);
- X free(awi);
- X }
- X Leave(FALSE)
- X
- X case PropertyNotify:
- X win = b_ev->xproperty.window;
- X if (!(awi = GetAwmInfo(win)))
- X Leave(FALSE)
- X switch(b_ev->xproperty.atom) {
- X
- X case XA_WM_COMMAND:
- X case XA_WM_HINTS:
- X case XA_WM_CLIENT_MACHINE:
- X break;
- X
- X case XA_WM_ICON_NAME:
- X /*
- X * Icon was modified by type-in (I still think that's a
- X * gross feature, but some people like it... sigh),
- X * ignore this event.
- X */
- X if (Icon_modified == TRUE) {
- X Icon_modified = FALSE; /* reset */
- X Leave(FALSE)
- X }
- X if (awi->icon && awi->own && awi->iconPixmap == IBackPixmap) {
- X win = awi->icon;
- X status = XGetWindowAttributes(dpy, win, &win_info);
- X icon_str = GetIconName(awi->client);
- X icon_str_len = icon_str ? strlen(icon_str) : 0;
- X if (win_info.width != XTextWidth(IFontInfo, ICONSTR,
- X strlen(ICONSTR)) +
- X (HIconPad << 1)) {
- X XResizeWindow(dpy, win,
- X XTextWidth(IFontInfo, ICONSTR,
- X strlen(ICONSTR)) +
- X (HIconPad << 1), IFontInfo->ascent +
- X IFontInfo->descent + (VIconPad << 1));
- X }
- X XClearWindow(dpy, win);
- X if (icon_str_len != 0) {
- X XDrawImageString(dpy, win, IconGC, HIconPad,
- X VIconPad+IFontInfo->ascent, icon_str,
- X icon_str_len);
- X free(icon_str);
- X }
- X }
- X break;
- X
- X case XA_WM_ICON_SIZE:
- X break;
- X
- X case XA_WM_NAME:
- X if (awi->title) {
- X if (awi->name)
- X free(awi->name);
- X awi->name = (char *)GetTitleName(win);
- X PaintTitle(win, (FocusWindow == awi->client));
- X }
- X break;
- X
- X case XA_WM_NORMAL_HINTS:
- X case XA_WM_SIZE_HINTS:
- X case XA_WM_ZOOM_HINTS:
- X break;
- X
- X default:
- X fprintf(stderr, "awm: Got unknown property %d\n",
- X b_ev->xproperty.atom);
- X }
- X Leave(FALSE)
- X break;
- X
- X
- X case Expose:
- X win = b_ev->xexpose.window;
- X if (!(awi = GetAwmInfo(win))) /* probably a menu */
- X Leave(FALSE)
- X if (awi->title == win) {
- X if (b_ev->xexpose.count == 0) {
- X XEvent evt;
- X
- X /* Eat up any previous exposes */
- X while (XCheckTypedWindowEvent(dpy, awi->title, Expose,
- X &evt));
- X PaintTitle(win, (FocusWindow == awi->client));
- X if (awi->gadgets)
- X PaintGadgets(win);
- X }
- X Leave(FALSE)
- X }
- X break;
- X
- X default:
- X break;
- X }
- X
- X /*
- X * If we got this far, the event must be for an icon.
- X */
- X win = b_ev->xany.window;
- X if (!(awi = GetAwmInfo(win)))
- X Leave(FALSE)
- X status = XGetWindowAttributes(dpy, win, &win_info);
- X if (status == FAILURE)
- X Leave(FALSE)
- X
- X if (b_ev->type == MapNotify ||
- X b_ev->type == UnmapNotify ||
- X b_ev->type == CreateNotify ||
- X b_ev->type == ReparentNotify ||
- X b_ev->type == GravityNotify ||
- X b_ev->type == CirculateNotify ||
- X b_ev->type == ConfigureNotify)
- X Leave(FALSE)
- X
- X /*
- X * Initialize the icon position variables.
- X */
- X icon_x = win_info.x;
- X icon_y = win_info.y;
- X
- X /*
- X * Get the name of the window associated with the icon and
- X * determine its length.
- X */
- X if (!awi->icon)
- X Leave(FALSE)
- X /*
- X * If we don't own it, or it's got a background pixmap, we don't have
- X * to repaint it.
- X */
- X if (!awi->own || (awi->iconPixmap != IBackPixmap))
- X Leave(FALSE)
- X icon = awi->icon;
- X icon_str = GetIconName(awi->client);
- X icon_str_len = icon_str ? strlen(icon_str) : 0;
- X
- X /*
- X * If the event is a window exposure event and the icon's name string
- X * is not of zero length, simply repaint the text in the icon window
- X * and return FALSE.
- X */
- X if (b_ev->type == Expose && (!Freeze || Frozen == 0)) {
- X if (win_info.width != XTextWidth(IFontInfo, ICONSTR,
- X strlen(ICONSTR))+(HIconPad << 1)) {
- X XResizeWindow(dpy, icon,
- X XTextWidth(IFontInfo, ICONSTR,
- X strlen(ICONSTR)) + (HIconPad << 1),
- X IFontInfo->ascent + IFontInfo->descent +
- X (VIconPad << 1));
- X }
- X XClearWindow(dpy, icon);
- X if (icon_str_len != 0) {
- X XDrawImageString(dpy, icon,
- X IconGC, HIconPad, VIconPad+IFontInfo->ascent,
- X icon_str, icon_str_len);
- X /*
- X * Remember to free the icon name string.
- X */
- X free(icon_str);
- X }
- X Leave(FALSE)
- X }
- X
- X#ifndef NO_ICON_TYPIN
- X /*
- X * If we have gotten this far event can only be a key pressed event.
- X */
- X kp_event = (XKeyPressedEvent *) b_ev;
- X
- X /*
- X * We convert the key pressed event to ascii.
- X */
- X nbytes = XLookupString(kp_event, kbd_str, STRLEN, NULL);
- X
- X /*
- X * If kbd_str is a "non-string", then don't do anything.
- X */
- X if (nbytes == 0) {
- X if (icon_str)
- X free(icon_str);
- X Leave(FALSE)
- X }
- X for (i = 0; i < nbytes; i++) {
- X key_char = kbd_str[i];
- X /*
- X * If the key was <DELETE>, then delete a character from the end of
- X * the name, return FALSE.
- X *
- X * If the key was <CTRL-U>, then wipe out the entire window name
- X * and return FALSE.
- X *
- X * All other ctrl keys are squashed and we return FALSE.
- X *
- X * All printable characters are appended to the window's name, which
- X * may have to be grown to allow for the extra length.
- X */
- X if (key_char == '\177') {
- X /*
- X * <DELETE>
- X */
- X if (icon_str_len > 0) {
- X icon_str_len--;
- X icon_str[icon_str_len] = '\0';
- X }
- X }
- X else if (key_char == '\025') {
- X /*
- X * <CTRL-U>
- X */
- X if (icon_str_len > 0) {
- X icon_str_len = 0;
- X icon_str[0] = '\0';
- X }
- X }
- X else if (key_char < IFontInfo->min_char_or_byte2 ||
- X key_char > IFontInfo->max_char_or_byte2) {
- X /*
- X * Any other random (non-printable) key; ignore it.
- X */
- X /* do nothing */ ;
- X }
- X else {
- X /*
- X * ASCII Alphanumerics.
- X */
- X if (icon_str == NULL)
- X icon_str = (char *) malloc (icon_str_len + 2);
- X else
- X icon_str = (char *)realloc(icon_str, (icon_str_len + 2));
- X if (icon_str == NULL) {
- X errno = ENOMEM;
- X Error("GetButton -> Realloc of window name string memory failed.");
- X }
- X icon_str[icon_str_len] = key_char;
- X icon_str[icon_str_len + 1] = '\0';
- X icon_str_len += 1;
- X }
- X }
- X
- X /*
- X * Now that we have changed the size of the icon we have to reconfigure
- X * it so that everything looks good. Oh yes, don't forget to move the
- X * mouse so that it stays in the window!
- X */
- X
- X /*
- X * Set the window name to the new string. Icon_modified is a kludge
- X * that tells us to avoid the next PropertyNotify, as it's a result of
- X * this call.
- X */
- X XSetIconName(dpy, awi->client, ICONSTR);
- X Icon_modified = TRUE;
- X /*
- X * Determine the new icon window configuration.
- X */
- X icon_h = IFontInfo->ascent + IFontInfo->descent + (VIconPad << 1);
- X icon_w = XTextWidth(IFontInfo, ICONSTR, strlen(ICONSTR));
- X if (icon_w == 0) {
- X icon_w = icon_h;
- X }
- X else {
- X icon_w += (HIconPad << 1);
- X }
- X
- X if (icon_x < 0) icon_x = 0;
- X if (icon_y < 0) icon_y = 0;
- X if (icon_x - 1 + icon_w + (IBorderWidth << 1) > ScreenWidth) {
- X icon_x = ScreenWidth - icon_w - (IBorderWidth << 1) + 1;
- X }
- X if (icon_y - 1 + icon_h + (IBorderWidth << 1) > ScreenHeight) {
- X icon_y = ScreenHeight - icon_h - (IBorderWidth << 1) + 1;
- X }
- X
- X XMoveResizeWindow(dpy, icon, icon_x, icon_y, icon_w, icon_h);
- X XWarpPointer(dpy, None, icon,
- X 0, 0, 0, 0, (icon_w >> 1), (icon_h >> 1));
- X
- X /*
- X * Free the local storage and return FALSE.
- X */
- X if (icon_str)
- X free(icon_str);
- X#endif
- X Leave(FALSE)
- X}
- X
- XCheckMap(window)
- XWindow window;
- X{
- X XWMHints *XGetWMHints();
- X XWMHints *wmhints;
- X int x, y, w, h;
- X Window transient_for;
- X Window jW;
- X int border_width, j;
- X Binding *bptr;
- X AwmInfoPtr awi;
- X unsigned long event_mask;
- X
- X Entry("CheckMap")
- X
- X /* if it's a transient window, we won't rubber-band
- X * note that this call always sets transient_for.
- X */
- X if (!XGetTransientForHint( dpy, window, &transient_for )) {
- X /*
- X * Handle any registered grabs for this window. We do this here
- X * because we may be about to make an icon out of this window
- X * and we want to register any potential grabs on it before this
- X * happens.
- X */
- X awi = GetAwmInfo(window);
- X if (!awi) {
- X for (bptr = Blist; bptr; bptr = bptr->next)
- X if (bptr->context & WINDOW)
- X Grab(bptr->mask, window);
- X awi = RegisterWindow(window);
- X Decorate(awi->client);
- X event_mask = PropertyChangeMask | FocusChangeMask;
- X if (!FrameFocus)
- X event_mask |= (EnterWindowMask | LeaveWindowMask);
- X XSelectInput(dpy, window, event_mask);
- X SetBorderPixmaps(dpy, GrayPixmap);
- X }
- X if ((wmhints = XGetWMHints(dpy, window))) {
- X if ((wmhints->flags & StateHint) && (awi->state & ST_WINDOW) &&
- X (wmhints->initial_state == IconicState)) {
- X /* window wants to be created as an icon. Leave size
- X /* and position alone, create as icon. */
- X XFree(wmhints);
- X Iconify(window, 0, 0, 0, 0);
- X Leave_void
- X }
- X XFree(wmhints);
- X }
- X }
- X else if ((awi = GetAwmInfo(window)) == NULL)
- X awi = RegisterWindow(window);
- X if (awi->state & ST_WINDOW) {
- X if (!transient_for)
- X PlaceWindow(window);
- X XMapRaised(dpy, awi->frame);
- X XMapWindow(dpy, awi->client);
- X XSync(dpy, 0);
- X }
- X Leave_void
- X}
- X
- XConfigure(event)
- XXConfigureRequestEvent *event;
- X{
- X XWindowChanges values;
- X AwmInfoPtr awi;
- X
- X Entry("Configure")
- X
- X values.x = event->x;
- X values.y = event->y;
- X values.width = event->width;
- X values.height = event->height;
- X values.border_width = event->border_width;
- X values.stack_mode = event->detail;
- X values.sibling = event->above;
- X
- X ConfigureWindow(event->window, event->value_mask, &values);
- X Leave_void
- X}
- X
- XCirculate(event)
- XXCirculateEvent *event;
- X{
- X Entry("Circulate")
- X
- X if (event->place == PlaceOnTop)
- X XRaiseWindow(event->display, event->window);
- X else
- X XLowerWindow(event->display, event->window);
- X Leave_void
- X}
- X
- XPlaceWindow(window)
- XWindow window;
- X{
- X XSizeHints wsh;
- X int x, y, w, h;
- X Boolean configureit = False;
- X XWindowChanges xwc;
- X AwmInfoPtr awi;
- X long flags;
- X
- X wsh.flags = 0;
- X flags = CWX | CWY | CWWidth | CWHeight;
- X awi = GetAwmInfo(window);
- X XGetSizeHints(dpy, window, &wsh, XA_WM_NORMAL_HINTS);
- X CheckConsistency(&wsh);
- X AskUser(dpy, scr, window, &x, &y, &w, &h, &wsh);
- X
- X wsh.flags |= (USPosition | USSize);
- X wsh.x = x;
- X wsh.y = y;
- X wsh.width = w;
- X wsh.height = h;
- X if (x < 0 || y < 0) {
- X Window jW;
- X int j, border_width;
- X
- X XGetGeometry(dpy, window, &jW, &j, &j, &j, &j, &border_width, &j);
- X
- X if (x < 0)
- X x += DisplayWidth(dpy, scr) - w - (border_width<<1);
- X if (y < 0)
- X y += DisplayHeight(dpy, scr) - h - (border_width<<1);
- X }
- X if (awi->frame)
- X XSetSizeHints(dpy, awi->frame, &wsh, XA_WM_NORMAL_HINTS);
- X XSetSizeHints(dpy, awi->client, &wsh, XA_WM_NORMAL_HINTS);
- X#ifdef titan /* 5x4 alignment */
- X x += (x % 5);
- X y += (y % 4);
- X#endif
- X xwc.x = x;
- X xwc.y = y;
- X xwc.height = h;
- X xwc.width = w;
- X ConfigureWindow(window, flags, &xwc);
- X awi->state |= ST_PLACED;
- X}
- X
- XBoolean ConfigureWindow(w, mask, xwc)
- XWindow w;
- Xunsigned long mask;
- XXWindowChanges *xwc;
- X{
- X XWindowAttributes xwa;
- X AwmInfoPtr awi;
- X int height, width, x, y;
- X int bch = 0, bcv = 0;
- X Entry("ConfigureWindow")
- X
- X awi = GetAwmInfo(w);
- X if (!awi)
- X Leave(FALSE)
- X
- X if (awi->attrs & AT_BORDER) {
- X bcv = BContext + 1;
- X bch = bcv * 2;
- X }
- X
- X height = xwc->height;
- X width = xwc->width;
- X x = y = 0;
- X /* width */
- X xwc->width += bch;
- X if (awi->title)
- X XResizeWindow(dpy, awi->title, xwc->width, titleHeight);
- X /* height */
- X if (awi->attrs & AT_TITLE) {
- X y = titleHeight + 2;
- X xwc->height += y;
- X }
- X if (awi->attrs & AT_BORDER) {
- X if (!(awi->attrs & AT_TITLE)) {
- X xwc->height += (bcv * 2);
- X y = bcv;
- X }
- X else
- X xwc->height += bcv;
- X xwc->x -= (BContext + (awi->border_width ? awi->border_width : 1));
- X x = BContext;
- X }
- X if (PushDown == FALSE) {
- X if (awi->attrs & AT_TITLE)
- X xwc->y -= (titleHeight + 2);
- X else if (awi->attrs & AT_BORDER)
- X xwc->y -= (BContext + (awi->border_width ?
- X awi->border_width : 1));
- X }
- X XConfigureWindow(dpy, awi->frame, mask, xwc);
- X if (awi->gadgets)
- X PutGadgets(w);
- X xwc->width = width;
- X xwc->height = height;
- X xwc->x = x;
- X xwc->y = y;
- X XConfigureWindow(dpy, awi->client, mask, xwc);
- X Leave(TRUE)
- X}
- X
- Xint
- XProcessRequests(box, num_vectors)
- XXSegment *box;
- Xint num_vectors;
- X{
- X XEvent event;
- X
- X XPeekEvent(dpy, &event);
- X switch (event.type) {
- X
- X case MapRequest:
- X case ConfigureRequest:
- X case CirculateRequest:
- X
- X DrawBox();
- X GetButton(&event);
- X DrawBox();
- X return TRUE;
- X }
- X return FALSE;
- X}
- END_OF_awm/GetButton.c
- if test 21347 -ne `wc -c <awm/GetButton.c`; then
- echo shar: \"awm/GetButton.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f awm/menus/track_menu.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"awm/menus/track_menu.c\"
- else
- echo shar: Extracting \"awm/menus/track_menu.c\" \(26723 characters\)
- sed "s/^X//" >awm/menus/track_menu.c <<'END_OF_awm/menus/track_menu.c'
- X#ident "%W% %G%"
- X
- X#ifndef lint
- X static char sccs_id[] = "@(#)track_menu.c 2.1 12/16/87 Siemens Corporate Research and Support, Inc.";
- X#endif
- X
- X
- X#include "X11/copyright.h"
- X
- X/*
- X RTL Menu Package Version 1.0
- X by Joe Camaratta and Mike Berman, Siemens RTL, Princeton NJ, 1987
- X
- X track_menu.c: bring up menus and track the mouse
- X */
- X
- X/*
- X *
- X * Copyright 1987, 1988 by Ardent Computer Corporation, Sunnyvale, Ca.
- X *
- X * Copyright 1987 by Jordan Hubbard.
- X *
- X *
- X * All Rights Reserved
- X *
- X * Permission to use, copy, modify, and distribute this software and its
- X * documentation for any purpose and without fee is hereby granted,
- X * provided that the above copyright notice appear in all copies and that
- X * both that copyright notice and this permission notice appear in
- X * supporting documentation, and that the name of Ardent Computer
- X * Corporation or Jordan Hubbard not be used in advertising or publicity
- X * pertaining to distribution of the software without specific, written
- X * prior permission.
- X *
- X */
- X
- X
- X/*
- X
- X Copyright 1987 by
- X Siemens Corporate Research and Support, Inc., Princeton, New Jersey
- X
- X Permission to use, copy, modify, and distribute this software
- X and its documentation for any purpose and without fee is
- X hereby granted, provided that the above copyright notice
- X appear in all copies and that both that copyright notice and
- X this permission notice appear in supporting documentation, and
- X that the name of Siemens not be used in advertising or
- X publicity pertaining to distribution of the software without
- X specific, written prior permission. Siemens makes no
- X representations about the suitability of this software for any
- X purpose. It is provided "as is" without express or implied
- X warranty.
- X
- X */
- X
- X/*
- X * The menu package will break if you don't define this, but
- X * it's there in case you want to see just how and where the
- X * "eventstack" stuff is used and, if necessary, replace it.
- X */
- X#define SAVE_EVENTS
- X
- X
- X#include <stdio.h>
- X#include "X11/Xlib.h"
- X#include "X11/cursorfont.h"
- X#include "arrow_icon.h"
- X#include "null_icon.h"
- X#include "menu.h"
- X#include "menu.def.h"
- X#include "menu.ext.h"
- X#include "dbug.h"
- X#ifdef SAVE_EVENTS
- X#include "eventstack.h"
- X#endif
- X
- X#define MIN(x,y) (((x) <= (y))? x:y)
- X#define MAX(x,y) (((x) >= (y))? x:y)
- X
- X#define CLICK_TIME 290 /* in milliseconds */
- X
- X#define CursorLockMask (ButtonReleaseMask | ExposureMask)
- X
- X/* Event macros */
- X
- X#define EventGetXCoord(rep) ((rep).xmotion.x)
- X#define EventGetYCoord(rep) ((rep).xmotion.y)
- X#define EventType(rep) ((rep).type)
- X#define EventXWindow(rep) ((rep).xcrossing.window)
- X#define EventXTime(rep) ((rep).xcrossing.time)
- X#define EventXMode(rep) ((rep).xcrossing.mode)
- X#define EventXRootX(rep) ((rep).xcrossing.x_root)
- X#define EventXRootY(rep) ((rep).xcrossing.y_root)
- X#define EventXDetail(rep) ((rep).xcrossing.detail)
- X#define EventMWindow(rep) ((rep).xmotion.window)
- X#define EventMTime(rep) ((rep).xmotion.time)
- X#define EventButton(rep) ((rep).xbutton.button)
- X#define EventBWindow(rep) ((rep).xbutton.window)
- X#define EventBTime(rep) ((rep).xbutton.time)
- X#define EventEX(rep) ((rep).xexpose.x)
- X#define EventEY(rep) ((rep).xexpose.y)
- X#define EventEWidth(rep) ((rep).xexpose.width)
- X#define EventEHeight(rep) ((rep).xexpose.height)
- X#define PointerEvent(rep) \
- X ((EventType(rep) == ButtonPress) || \
- X (EventType(rep) == ButtonRelease) || \
- X (EventType(rep) == MotionNotify) || \
- X (EventType(rep) == EnterNotify) || \
- X (EventType(rep) == LeaveNotify) || \
- X (EventType(rep) == FocusIn) || \
- X (EventType(rep) == FocusOut))
- X#define KeyEvent(rep) \
- X ((EventType(rep) == KeyPress) || (EventType(rep) == KeyRelease))
- X/* Possible states for the state machine */
- Xtypedef enum
- X{
- X Initial, /* Inside a submenu, but not any item */
- X CheckTrigger, /* Inside an item that has submenu, checking for pullright */
- X Leaf, /* Inside an item with no submenu */
- X Exit, /* Preparing to exit */
- X LevelControl /* Not in any submenu, waiting to enter something */
- X } State;
- X
- XState InitialState(), CheckTriggerState(), LeafState(), LevelControlState(),
- X GetItemState();
- Xbool EventNotSignificant(), PushSubmenu();
- X
- Xvoid OutputEvent(), GetNextSignificantEvent(), PopSubmenu(),
- X Highlight(), Unhighlight(), DisplayInitialMenus(), LockCursor(),
- X TossExtraMoves(), UnlockCursor();
- X
- Xvoid ProcessExposeEvents();
- X
- Xvoid SaveTest();
- X
- XMenuItem *MenuGetItem();
- XMenu *MenuGetMenu();
- X
- X/* global state variables */
- X
- Xstatic MenuItem *current_item;
- Xstatic Menu *current_menu;
- Xstatic Window root_window;
- Xextern Display *dpy;
- Xextern int scr;
- Xstatic int level; /* submenu level */
- Xstatic Time button_time; /* time button press invoked */
- Xstatic Cursor wait_cursor = None; /* empty cursor for lock state */
- Xstatic bool click_allowed;
- Xstatic bool lock_event_mask, unlock_event_mask;
- X
- Xextern int Autoselect;
- Xextern int MDelta;
- X
- X#ifdef SAVE_EVENTS
- Xstatic struct Ev_q *ev_save = 0;
- X#endif
- X
- X
- XMenuItem *TrackMenu(root_menu, root_x, root_y,
- X init_button, root, buttime)
- XMenu *root_menu; /* Pointer to root menu requested to pop up */
- Xint root_x, root_y; /* Position to start menu */
- Xint init_button; /* The # of button used to pop up menu */
- XWindow root; /* Window label for parent of menu */
- XTime buttime; /* timestamp for button (or 0, if CLICK == 0) */
- X{
- X State CurrentState = LevelControl;
- X XEvent Event_Reply;
- X int open_x;
- X bool selected = FALSE;
- X MenuItem *selected_item;
- X
- X Entry("TrackMenu")
- X
- X /* Initialize globals */
- X
- X button_time = buttime;
- X root_window = root;
- X level = 0;
- X current_menu = root_menu;
- X click_allowed = (TestOptionFlag(current_menu, clickokay))? TRUE : FALSE;
- X unlock_event_mask = (TestOptionFlag(current_menu, savebits))?
- X MenuEventMask : (MenuEventMask | ExposureMask);
- X lock_event_mask = (TestOptionFlag(current_menu, savebits))?
- X CursorLockMask : (CursorLockMask | ExposureMask);
- X
- X /* If not already done, set up the null cursor for lock state */
- X if (wait_cursor == None)
- X {
- X Pixmap wc_pixmap;
- X XColor fg, bg;
- X
- X wc_pixmap = XCreateBitmapFromData (dpy, root_window,
- X null_icon_bits,
- X null_icon_width, null_icon_height);
- X wait_cursor = XCreatePixmapCursor (dpy, wc_pixmap, wc_pixmap,
- X &fg, &bg, 1, 1);
- X }
- X
- X
- X /* Block all other action by grabbing the server */
- X /* XGrabServer (dpy); */
- X /* Don't think we need to grab the server... so for now, we won't */
- X
- X#ifdef SAVE_EVENTS
- X /* Get the present state, so it can be restored later */
- X /* Any events on the queue when we start get saved now, restored later */
- X SaveEvents (dpy, &ev_save, ~(unsigned long) ButtonReleaseMask);
- X#endif
- X
- X LockCursor(root_window);
- X if (!(current_item =
- X Display_Menu(current_menu, NULLMENU, root_x, root_y)))
- X {
- X CurrentState = Exit;
- X }
- X /*
- X * First item is a label and autoselect is on, so we want
- X * to push on to the first "real" item.
- X */
- X if (ItemIsDeaf(current_item) && Autoselect)
- X current_item = current_item->nextItem;
- X LockCursor(ItemWindow(current_item));
- X open_x = root_x;
- X
- X /* Push to appropriate previous item, if any */
- X while (MenuHasInitialItem(current_menu) && (CurrentState != Exit))
- X {
- X current_item = GetInitialItem(current_menu);
- X ClearInitialItem(current_menu);
- X
- X /* if the initial item can't be selected, take first in list */
- X if (ItemIsNull(current_item) || ItemIsDisabled(current_item))
- X {
- X current_item = MenuItems(current_menu);
- X break;
- X }
- X else if (ItemIsLeaf(current_item)) /* then we're done */
- X break;
- X else
- X {
- X open_x += ItemGetArrowPosition(current_item);
- X if (!ItemIsDeaf(current_item))
- X Highlight(current_item);
- X TossExtraMoves(ItemWindow(current_item));
- X (void)PushSubmenu(open_x);
- X }
- X }
- X ProcessExposeEvents();
- X if (CurrentState != Exit)
- X CurrentState = (ItemIsLeaf(current_item)) ? Leaf : CheckTrigger;
- X if (!ItemIsDeaf(current_item))
- X Highlight(current_item);
- X XSync (dpy, 0); /* get release click, if it's in queue */
- X#ifdef SAVE_EVENTS
- X DisposeEvents(dpy, (PointerMotionMask | EnterWindowMask |
- X LeaveWindowMask | ExposureMask));
- X#endif
- X LockCursor(ItemWindow(current_item));
- X PlacePointer(current_menu,current_item);
- X UnlockCursor();
- X
- X /* State Machine */
- X
- X while (CurrentState != Exit)
- X {
- X GetNextSignificantEvent(&Event_Reply, init_button);
- X switch (CurrentState)
- X {
- X case LevelControl:
- X CurrentState = LevelControlState(Event_Reply);
- X break;
- X case Initial:
- X CurrentState = InitialState(Event_Reply);
- X break;
- X case CheckTrigger:
- X CurrentState = CheckTriggerState(Event_Reply);
- X break;
- X case Leaf:
- X CurrentState = LeafState(Event_Reply, &selected);
- X break;
- X default:
- X Retch("(RTLmenu) YOW! Unknown State! (%d)\n",
- X CurrentState);
- X CurrentState = Exit;
- X break;
- X }
- X }
- X /* Clean up and exit */
- X
- X selected_item = (selected)? current_item : NULLITEM;
- X while (level)
- X {
- X if (selected)
- X SetInitialItem(current_menu, current_item);
- X PopSubmenu();
- X }
- X if (selected)
- X {
- X SetInitialItem(current_menu, current_item);
- X }
- X
- X Undisplay_Menu(current_menu);
- X UnlockCursor();
- X XUngrabPointer(dpy, CurrentTime);
- X
- X /* Throw out any left over events from menu world */
- X /* if (TestOptionFlag(current_menu, savebits)) {
- X XSync(dpy,1);
- X XUngrabServer(dpy, CurrentTime); add this if grab added!
- X }
- X else
- X XSync(dpy,0);*/
- X
- X /* Push back any events that were lying around when menus started */
- X
- X XFlush(dpy);
- X#ifdef SAVE_EVENTS
- X DisposeEvents(dpy, (PointerMotionMask | EnterWindowMask |
- X LeaveWindowMask | ExposureMask));
- X RestoreEvents(dpy, &ev_save);
- X#endif
- X Leave(selected_item)
- X}
- X
- X/* Used for debugging */
- X
- Xvoid OutputEvent(Event_Reply)
- XXEvent Event_Reply;
- X{
- X Entry("OutputEvent")
- X
- X switch (EventType(Event_Reply))
- X {
- X case ButtonPress:
- X case ButtonRelease:
- X DBUG_5("RTLmenu","Button Press/Release, button %d on window %d at time %d\n",
- X EventButton(Event_Reply), EventBWindow(Event_Reply),
- X EventBTime(Event_Reply));
- X break;
- X case MotionNotify:
- X DBUG_5("RTLmenu","Motion Notify on window %d at time %d, x=%d\n",
- X EventMWindow(Event_Reply), EventMTime(Event_Reply),
- X EventGetXCoord(Event_Reply));
- X break;
- X case EnterNotify:
- X DBUG_4("RTLmenu","Enter Notify on window %d at time %d\n",
- X EventXWindow(Event_Reply), EventXTime(Event_Reply));
- X break;
- X case LeaveNotify:
- X DBUG_4("RTLmenu","Leave Notify on window %d at time %d\n",
- X EventXWindow(Event_Reply), EventXTime(Event_Reply));
- X break;
- X default:
- X DBUG_3("RTLmenu","Unexpected event type %d\n", EventType(Event_Reply));
- X break;
- X }
- X Leave_void
- X}
- X
- Xstatic bool locked = FALSE;
- X
- X/* Lock the cursor: make it disappear, and ignore events it generates. */
- X/* Optionally, confine it to a single window. */
- X/* (Using "None" for confine_window doesn't confine it. ) */
- Xvoid LockCursor(confine_window)
- XWindow confine_window;
- X{
- X int result;
- X
- X Entry("LockCursor")
- X
- X locked = TRUE;
- X result = XGrabPointer(dpy,
- X RootWindow(dpy, MenuScreen(current_menu)),
- X True, lock_event_mask, GrabModeSync,
- X GrabModeAsync, confine_window,
- X wait_cursor, CurrentTime);
- X DBUG_3("RTLmenu","Lock Cursor grab = %d\n",result);
- X Leave_void
- X}
- X
- X/* Unlock (and unconfine) the cursor. If cursor lock is not set, */
- X/* this does nothing. */
- X
- Xvoid UnlockCursor()
- X{
- X int result;
- X
- X Entry("UnlockCursor")
- X
- X if (locked)
- X {
- X locked = FALSE;
- X result = XGrabPointer(dpy,
- X RootWindow(dpy, MenuScreen(current_menu)),
- X True, unlock_event_mask,
- X GrabModeAsync, GrabModeAsync, None,
- X MenuCursor(current_menu), CurrentTime);
- X DBUG_3("RTLmenu","Unlock Cursor grab = %d\n",result);
- X }
- X Leave_void
- X}
- X
- X/* Keep getting the X events, until finding one that may be interesting */
- X/* to the operation of the state machine. */
- X
- Xvoid GetNextSignificantEvent(Event_Reply,init_button)
- XXEvent *Event_Reply;
- Xint init_button; /* the button that initiated the menu */
- X{
- X XEvent Next_Event_Reply;
- X bool InsignificantEvent = True;
- X
- X Entry("GetNextSignificantEvent")
- X
- X /* Loop as long as any of a number of "insignificant" events */
- X /* are found; when the event no longer matches one of the tests, */
- X /* it is assumed to be "significant" and returned.*/
- X do
- X {
- X XNextEvent(dpy, Event_Reply);
- X DBUG_EXECUTE("RTLmenu", OutputEvent(*Event_Reply));
- X
- X /* If this event is an "enter", check whether there is a */
- X /* "leave" for the same window already in the queue, */
- X /* immediately following it; if so, throw them both out */
- X /* and get the next event */
- X /* NOTE: might try to look further ahead, but this is */
- X /* tricky because other events might intervene. */
- X
- X if ((EventType(*Event_Reply) == EnterNotify) &&
- X (EventXMode(*Event_Reply) == NotifyNormal) &&
- X (QLength(dpy) > 0) &&
- X (MenuGetMenu(current_menu, EventXWindow(*Event_Reply))
- X != current_menu))
- X {
- X XPeekEvent(dpy, &Next_Event_Reply);
- X if ((EventType(Next_Event_Reply) == LeaveNotify) &&
- X (EventXMode(Next_Event_Reply) == NotifyNormal) &&
- X (EventXWindow(Next_Event_Reply) == EventXWindow(*Event_Reply)))
- X {
- X DBUG_2("RTLmenu","TOSS: Enter/leave pair.\n");
- X XNextEvent(dpy, Event_Reply);
- X XNextEvent(dpy, Event_Reply);
- X }
- X }
- X#ifdef SAVE_EVENTS
- X if (EventNotSignificant(*Event_Reply, init_button))
- X {
- X if (!(PointerEvent(*Event_Reply) || KeyEvent(*Event_Reply)
- X || EventType(*Event_Reply) == Expose))
- X {
- X /* might be significant elsewhere -- save it for later */
- X AddEventToStore(&ev_save, *Event_Reply);
- X }
- X }
- X else
- X#else
- X if (!EventNotSignificant(*Event_Reply, init_button))
- X#endif
- X InsignificantEvent = FALSE;
- X }
- X while (InsignificantEvent);
- X
- X DBUG_2("RTLmenu","--->");
- X Leave_void
- X}
- X
- X/* Check whether the event matches one of the events considered */
- X/* "not significant".*/
- Xbool EventNotSignificant(Event_Reply, init_button)
- XXEvent Event_Reply;
- Xint init_button;
- X{
- X Entry("EventNotSignificant")
- X
- X /* Insignificant if not in following list */
- X Leave(!((EventType(Event_Reply) == ButtonRelease) ||
- X (EventType(Event_Reply) == ButtonPress) ||
- X (EventType(Event_Reply) == MotionNotify) ||
- X (EventType(Event_Reply) == EnterNotify) ||
- X (EventType(Event_Reply) == Expose) ||
- X (EventType(Event_Reply) == LeaveNotify))
- X ||
- X /* Insignificant if leave or enter is not "Normal" */
- X (((EventType(Event_Reply) == LeaveNotify) ||
- X (EventType(Event_Reply) == EnterNotify)) &&
- X (EventXMode(Event_Reply) != NotifyNormal))
- X ||
- X /* Insignificant if hit button other than initial one */
- X ((EventType(Event_Reply) == ButtonRelease) &&
- X (EventButton(Event_Reply) != init_button))
- X ||
- X /* Insignificant if tail end of a click -- and clicks allowed */
- X (click_allowed &&
- X (EventType(Event_Reply) == ButtonRelease) &&
- X (EventBTime(Event_Reply) - button_time < CLICK_TIME))
- X )
- X}
- X
- XState LevelControlState(rep)
- XXEvent rep;
- X{
- X State next_state;
- X Menu *entered_menu;
- X MenuItem *entered_item;
- X
- X Entry("LevelControlState")
- X switch (EventType(rep))
- X {
- X case MotionNotify:
- X case LeaveNotify:
- X next_state = LevelControl; /* loop back to this state */
- X break;
- X case EnterNotify:
- X /* Decide whether we've entered a menu window or item window */
- X entered_menu = MenuGetMenu(current_menu, EventXWindow(rep));
- X entered_item = MenuGetItem(current_menu,EventXWindow(rep));
- X
- X if ((MenuIsNull(entered_menu)) && (ItemIsNull(entered_item)))
- X /* Must be some other window; carry on */
- X next_state = LevelControl;
- X else if (!ItemIsNull(entered_item) &&
- X MenuIsDisplayed(ItemMenu(entered_item)))
- X {
- X /* we entered an item, but not a window. This should only happen */
- X /* when we stayed in the parent of the current submenu. So, */
- X /* Pop that submenu and get to the item. */
- X if (level)
- X {
- X LockCursor(ItemWindow(entered_item));
- X PopSubmenu();
- X ProcessExposeEvents();
- X UnlockCursor();
- X current_item = entered_item;
- X Highlight(current_item);
- X next_state = GetItemState(rep);
- X }
- X else /* I must be very confused... */
- X {
- X Retch("(RTLmenu) Tried to pop the root menu...\n");
- X next_state = Exit;
- X }
- X }
- X
- X else if (!MenuIsNull(entered_menu)&&
- X MenuIsDisplayed(entered_menu))
- X {
- X /* entered a menu that is displayed */
- X while ((current_menu != entered_menu) && level)
- X /* drop down the menu that was entered */
- X PopSubmenu();
- X ProcessExposeEvents();
- X UnlockCursor();
- X if (current_menu == entered_menu)
- X next_state = Initial;
- X else
- X {
- X next_state = Exit;
- X Retch("(RTLmenu) Couldn't find the menu I entered!!\n");
- X }
- X }
- X else
- X next_state = LevelControl;
- X break;
- X case ButtonRelease:
- X next_state = Exit;
- X break;
- X default:
- X Retch("RTLmenu","YOW! Unexpected event! (%d)\n", rep.type);
- X next_state = Exit;
- X break;
- X }
- X Leave(next_state)
- X}
- X
- X/* Figure out the status of the item we've just entered */
- XState GetItemState(rep)
- XXEvent rep;
- X{
- X int open_x;
- X State next_state;
- X
- X Entry("GetItemState")
- X if (ItemIsNull(current_item))
- X {
- X Retch("(RTLmenu) null current item!");
- X next_state = Exit;
- X }
- X else if (MenuIsNull(current_menu))
- X {
- X Retch("(RTLmenu) null current menu!");
- X next_state = Exit;
- X }
- X else if (ItemIsLeaf(current_item))
- X {
- X if (MenuHasInitialItem(current_menu))
- X ClearInitialItem(current_menu);
- X next_state = Leaf;
- X }
- X else if (EventGetXCoord(rep) >= (int)(ItemGetArrowPosition(current_item) - 4))
- X {
- X /* entered item in "auto pop-up zone", i.e., over pull-right arrow. */
- X LockCursor(ItemWindow(current_item));
- X TossExtraMoves(ItemWindow(current_item));
- X if (PushSubmenu(EventXRootX(rep)))
- X {
- X LockCursor(ItemWindow(current_item));
- X PlacePointer(current_menu, current_item);
- X next_state = Initial;
- X ProcessExposeEvents();
- X }
- X else
- X next_state = CheckTrigger;
- X UnlockCursor();
- X }
- X else if (MenuHasInitialItem(current_menu))
- X {
- X /* Entered menu has initial item -- move to it */
- X DBUG_2("RTLmenu","Pushing for initial item.");
- X current_item = GetInitialItem(current_menu);
- X open_x = ItemGetArrowPosition(current_item) +
- X EventXRootX(rep);
- X ClearInitialItem(current_menu);
- X LockCursor(ItemWindow(current_item));
- X if (PushSubmenu(open_x))
- X {
- X ProcessExposeEvents();
- X LockCursor(ItemWindow(current_item));
- X PlacePointer(current_menu, current_item);
- X next_state = Initial;
- X }
- X UnlockCursor();
- X }
- X else /* parent pull */
- X next_state = CheckTrigger;
- X Leave(next_state)
- X}
- X
- XState InitialState( rep)
- XXEvent rep;
- X{
- X State next_state;
- X
- X Entry("Initial")
- X switch (EventType(rep))
- X {
- X case EnterNotify:
- X if (MenuIsNull(current_menu))
- X {
- X Retch("(RTLmenu) null current menu!?!?");
- X next_state = Exit;
- X }
- X else if (EventXDetail(rep) == NotifyInferior)
- X next_state = Initial;
- X else
- X {
- X current_item = MenuGetItem(current_menu, EventXWindow(rep));
- X if (ItemIsNull(current_item))
- X {
- X /* Retch("(RTLmenu) Window entered not an item!\n"); */
- X next_state = Exit;
- X }
- X else
- X {
- X Highlight(current_item);
- X next_state = GetItemState(rep);
- X }
- X }
- X break;
- X case LeaveNotify:
- X /* Decide whether we're actually leaving */
- X /* this menu for another submenu or the root, */
- X /* or going into an item. */
- X next_state = (EventXDetail(rep) == NotifyInferior)?
- X Initial : LevelControl;
- X break;
- X case ButtonRelease:
- X next_state = Exit;
- X break;
- X case MotionNotify:
- X next_state = Initial;
- X break;
- X default:
- X Retch("(RTLmenu) YOW! Unexpected event! (%d)\n", rep.type);
- X next_state = Exit;
- X break;
- X }
- X Leave(next_state)
- X}
- X
- X#define NotSet -1
- X/* Look to see if pull-right is requested */
- XState CheckTriggerState(rep)
- XXEvent rep;
- X{
- X State next_state = CheckTrigger;
- X static int Trigger = NotSet;
- X static int OldX, NewX, childX, button;
- X
- X Entry("CheckTrigger")
- X if (MenuIsNull(current_menu) || ItemIsNull(current_item))
- X {
- X Retch("(RTLmenu) Null menu or item...");
- X next_state = Exit;
- X goto exit;
- X }
- X if (Trigger == NotSet) /* set it */
- X {
- X Trigger = MIN(EventGetXCoord(rep) + MenuDelta(current_menu),
- X ItemGetArrowPosition(current_item));
- X NewX = NotSet;
- X }
- X switch (EventType(rep))
- X {
- X case LeaveNotify:
- X next_state = Initial;
- X Unhighlight(MenuGetItem(current_menu, EventXWindow(rep)));
- X Trigger = NotSet;
- X break;
- X case ButtonRelease:
- X next_state = Exit;
- X Trigger = NotSet;
- X break;
- X
- X case ButtonPress:
- X button = rep.xbutton.button;
- X while (TRUE) {
- X XNextEvent(dpy, &rep);
- X if (rep.type == ButtonRelease &&
- X rep.xbutton.button == button)
- X break;
- X }
- X next_state = CheckTrigger;
- X childX = TestOptionFlag(current_menu, fixedchild) ?
- X (MenuX(current_menu) + ItemGetArrowPosition(current_item)) :
- X EventXRootX(rep);
- X Trigger = NotSet;
- X if (PushSubmenu(childX))
- X {
- X next_state = LevelControl;
- X ProcessExposeEvents();
- X LockCursor(ItemWindow(current_item));
- X PlacePointer(current_menu, current_item);
- X }
- X UnlockCursor();
- X break;
- X
- X case MotionNotify:
- X next_state = CheckTrigger;
- X OldX = NewX;
- X NewX = EventGetXCoord(rep);
- X if (NewX >= Trigger)
- X {
- X LockCursor(ItemWindow(current_item));
- X childX = TestOptionFlag(current_menu, fixedchild)?
- X (MenuX(current_menu) + ItemGetArrowPosition(current_item)):
- X EventXRootX(rep);
- X Trigger = NotSet;
- X if (PushSubmenu(childX))
- X {
- X next_state = LevelControl;
- X ProcessExposeEvents();
- X LockCursor(ItemWindow(current_item));
- X PlacePointer(current_menu, current_item);
- X }
- X UnlockCursor();
- X }
- X else if (NewX < OldX) /* reverse motion */
- X Trigger = MIN(Trigger, NewX + MenuDelta(current_menu));
- X break;
- X
- X default:
- X Retch("(RTLmenu) YOW! Unexpected event!\n");
- X next_state = Exit;
- X break;
- X }
- X exit:
- X Leave(next_state)
- X}
- X
- XState LeafState(rep,selected)
- XXEvent rep;
- Xbool *selected;
- X{
- X State next_state;
- X
- X Entry("LeafState")
- X switch(EventType(rep))
- X {
- X case LeaveNotify:
- X Unhighlight(MenuGetItem(current_menu, EventXWindow(rep)));
- X next_state = Initial;
- X break;
- X
- X case ButtonRelease:
- X *selected = TRUE;
- X next_state = Exit;
- X break;
- X
- X case ButtonPress:
- X case EnterNotify:
- X case MotionNotify: /* if events set right, this never happens */
- X next_state = Leaf;
- X break;
- X
- X default:
- X Retch("(RTLMenu) YOW! Unexpected event! (%d)\n",
- X rep.type);
- X next_state = Exit;
- X break;
- X }
- X Leave(next_state)
- X}
- X
- Xbool PushSubmenu(x)
- Xint x;
- X{
- X int y;
- X bool pushed;
- X MenuItem *new_current_item;
- X
- X Entry("PushSubmenu")
- X
- X if (ItemIsNull(current_item))
- X {
- X Retch("(RTLMenu) Can't push from null item.\n");
- X pushed = FALSE;
- X }
- X else if (MenuIsNull(ItemSubmenu(current_item)))
- X {
- X Retch("(RTLmenu) Null submenu.\n");
- X pushed = FALSE;
- X }
- X else if (ItemIsNull(MenuItems(ItemSubmenu(current_item))))
- X /* submenu has no items -- don't push, but not an error */
- X pushed = FALSE;
- X else
- X {
- X y = ItemGetMiddleY(current_item);
- X ++level;
- X
- X if (new_current_item =
- X Display_Menu(ItemSubmenu(current_item), current_menu, x, y))
- X {
- X XFlush(dpy);
- X current_menu = ItemSubmenu(current_item);
- X current_item = new_current_item;
- X if (ItemIsDeaf(current_item) && Autoselect)
- X current_item = current_item->nextItem;
- X pushed = TRUE;
- X }
- X else
- X {
- X Retch("(RTLmenu) Display_Menu failed!\n");
- X pushed = FALSE;
- X }
- X }
- X Leave(pushed)
- X}
- X
- Xvoid PopSubmenu()
- X{
- X Menu *parent;
- X MenuItem *item;
- X
- X Entry("PopSubmenu")
- X --level;
- X parent = current_menu->parentMenu;
- X Undisplay_Menu(current_menu);
- X current_menu = parent;
- X if (!MenuIsNull(current_menu))
- X {
- X item = MenuItemHighlighted(current_menu);
- X if (!ItemIsNull(item))
- X {
- X current_item = item;
- X }
- X }
- X
- X Leave_void
- X}
- X
- Xvoid Highlight(item)
- XMenuItem *item;
- X{
- X MenuItem *old_highlight;
- X
- X Entry("Highlight")
- X
- X old_highlight = MenuItemHighlighted(current_menu);
- X if ((item != old_highlight) && /* else, already highlighted */
- X (!ItemIsNull(item)))
- X {
- X if (!ItemIsNull(old_highlight) && !ItemIsDeaf(item))
- X Unhighlight(old_highlight);
- X MenuInvert(ItemMenu(item), item);
- X SetHighlightItem(ItemMenu(item), item);
- X }
- X Leave_void
- X}
- X
- Xvoid Unhighlight(item)
- XMenuItem *item;
- X{
- X Entry("Unhighlight")
- X if (!ItemIsNull(item))
- X {
- X if (MenuItemHighlighted(current_menu) == item)
- X {
- X MenuInvert(ItemMenu(item), item);
- X ResetHighlightItem(ItemMenu(item));
- X }
- X }
- X Leave_void
- X}
- X
- Xvoid TossExtraMoves(window)
- XWindow window;
- X{
- X XEvent ev;
- X
- X Entry("TossExtraMoves")
- X /* XSync(dpy,0); /* make sure they're all on the queue */
- X while (XCheckTypedWindowEvent(dpy, window, MotionNotify, &ev))
- X DBUG_2("RTLmenu","Tossing extra motion.\n");
- X Leave_void
- X}
- X
- X
- Xvoid ProcessExposeEvents()
- X{
- X MenuItem *item;
- X XEvent ev;
- X
- X Entry("ProcessExposeEvents")
- X
- X XSync(dpy,0);
- X while (XCheckTypedEvent(dpy, Expose, &ev))
- X {
- X item = MenuGetItem(current_menu, EventXWindow(ev));
- X if (!ItemIsNull(item))
- X Draw_Item(ItemMenu(item), item, EventEX(ev), EventEY(ev),
- X EventEWidth(ev), EventEHeight(ev));
- X }
- X Leave_void
- X}
- END_OF_awm/menus/track_menu.c
- if test 26723 -ne `wc -c <awm/menus/track_menu.c`; then
- echo shar: \"awm/menus/track_menu.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- echo shar: End of archive 9 \(of 13\).
- cp /dev/null ark9isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 13 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
- Mike Wexler(wyse!mikew) Phone: (408)433-1000 x1330
-